"""
Case Type   : ustore_DQL_SET_OPERATIONS
Case Name   : minus多表联合查询
Create At   : 2022-05-12
Owner       : nanyang12
Description :
    1.创建表
    2.使用copy命令插入数据
    3.minus多表联合查询
    4.环境清理
Expect      :
    1.创建成功
    2.数据插入成功
    3.成功
    4.清理成功
History     :
"""

import os
import subprocess
import unittest

from testcase.utils.Common import Common
from testcase.utils.CommonSH import CommonSH
from testcase.utils.Constant import Constant
from testcase.utils.Logger import Logger
from yat.test import Node
from yat.test import macro


class Ustore01(unittest.TestCase):
    def setUp(self):
        self.log = Logger()
        self.log.info(f'----- {os.path.basename(__file__)} start-----')
        self.pri_sh = CommonSH('PrimaryDbUser')
        self.pri_root = Node('PrimaryRoot')
        self.com = Common()
        self.constant = Constant()
        self.table_name1 = 't_ustore_Cast_minus_0001_01'
        self.table_name2 = 't_ustore_Cast_minus_0001_02'
        self.table_name3 = 't_ustore_Cast_minus_0001_03'
        self.table_name4 = 't_ustore_Cast_minus_0001_04'
        self.table_name5 = 't_ustore_Cast_minus_0001_05'
        self.copy_file1 = 'store_33.txt'
        self.copy_file2 = 'item_33.txt'
        self.copy_file3 = 'warehouse_33.txt'
        self.copy_file4 = 'ship_mode_33.txt'
        self.copy_file5 = 'reason_33.txt'
        self.cur_path_1 = os.path.join(macro.SCRIPTS_PATH, self.copy_file1)
        self.cur_path_2 = os.path.join(macro.SCRIPTS_PATH, self.copy_file2)
        self.cur_path_3 = os.path.join(macro.SCRIPTS_PATH, self.copy_file3)
        self.cur_path_4 = os.path.join(macro.SCRIPTS_PATH, self.copy_file4)
        self.cur_path_5 = os.path.join(macro.SCRIPTS_PATH, self.copy_file5)
        self.parent_path = os.path.dirname(macro.DB_INSTANCE_PATH)
        self.target_path1 = os.path.join(self.parent_path, self.copy_file1)
        self.target_path2 = os.path.join(self.parent_path, self.copy_file2)
        self.target_path3 = os.path.join(self.parent_path, self.copy_file3)
        self.target_path4 = os.path.join(self.parent_path, self.copy_file4)
        self.target_path5 = os.path.join(self.parent_path, self.copy_file5)

    def test_join(self):
        step_txt = '-----step1:创建表;expect: 创建成功-----'
        self.log.info(step_txt)
        cmd_sql = f"""drop table if exists {self.table_name1}  CASCADE ;
                    drop table if exists {self.table_name2}  CASCADE ;
                create table {self.table_name1}(
                    s_store_sk                integer               not null,
                    s_store_id                char(16)              not null,
                    s_rec_start_date          date                          ,
                    s_rec_end_date            date                          ,
                    s_closed_date_sk          integer                       ,
                    s_store_name              varchar(50)                   ,
                    s_number_employees        integer                       ,
                    s_floor_space             integer                       ,
                    s_hours                   char(20)                      ,
                    s_manager                 varchar(40)                   ,
                    s_market_id               integer                       ,
                    s_geography_class         varchar(100)                  ,
                    s_market_desc             varchar(100)                  ,
                    s_market_manager          varchar(40)                   ,
                    s_division_id             integer                       ,
                    s_division_name           varchar(50)                   ,
                    s_company_id              integer                       ,
                    s_company_name            varchar(50)                   ,
                    s_street_number           varchar(10)                   ,
                    s_street_name             varchar(60)                   ,
                    s_street_type             char(15)                      ,
                    s_suite_number            char(10)                      ,
                    s_city                    varchar(60)                   ,
                    s_county                  varchar(30)                   ,
                    s_state                   char(2)                       ,
                    s_zip                     char(10)                      ,
                    s_country                 varchar(20)                   ,
                    s_gmt_offset              decimal(5,2)                  ,
                    s_tax_precentage          decimal(5,2)                  
                 )  WITH (STORAGE_TYPE=USTORE);
                create table {self.table_name2}
                (
                    i_item_sk                 integer               not null,
                    i_item_id                 char(16)              not null,
                    i_rec_start_date          date                          ,
                    i_rec_end_date            date                          ,
                    i_item_desc               varchar(200)                  ,
                    i_current_price           decimal(7,2)                  ,
                    i_wholesale_cost          decimal(7,2)                  ,
                    i_brand_id                integer                       ,
                    i_brand                   char(50)                      ,
                    i_class_id                integer                       ,
                    i_class                   char(50)                      ,
                    i_category_id             integer                       ,
                    i_category                char(50)                      ,
                    i_manufact_id             integer                       ,
                    i_manufact                char(50)                      ,
                    i_size                    char(20)                      ,
                    i_formulation             char(20)                      ,
                    i_color                   char(20)                      ,
                    i_units                   char(10)                      ,
                    i_container               char(10)                      ,
                    i_manager_id              integer                       ,
                    i_product_name            char(50)                      
                )  WITH (STORAGE_TYPE=USTORE);
                create table {self.table_name3}
                (
                    w_warehouse_sk            integer               not null,
                    w_warehouse_id            char(16)              not null,
                    w_warehouse_name          varchar(20)                   ,
                    w_warehouse_sq_ft         integer                       ,
                    w_street_number           char(10)                      ,
                    w_street_name             varchar(60)                   ,
                    w_street_type             char(15)                      ,
                    w_suite_number            char(10)                      ,
                    w_city                    varchar(60)                   ,
                    w_county                  varchar(30)                   ,
                    w_state                   char(2)                       ,
                    w_zip                     char(10)                      ,
                    w_country                 varchar(20)                   ,
                    w_gmt_offset              decimal(5,2)
                 ) WITH (STORAGE_TYPE=USTORE);
                drop table if exists {self.table_name4}  CASCADE ;
                create table {self.table_name4}
                (
                    sm_ship_mode_sk           integer               not null,
                    sm_ship_mode_id           char(16)              not null,
                    sm_type                   char(30)                      ,
                    sm_code                   char(10)                      ,
                    sm_carrier                char(20)                      ,
                    sm_contract               char(20)
                ) WITH (STORAGE_TYPE=USTORE);
                create table {self.table_name5}
                (
                    r_reason_sk               integer               not null,
                    r_reason_id               char(16)              not null,
                    r_reason_desc             char(100)                    
                 ) WITH (STORAGE_TYPE=USTORE);"""
        self.log.info(cmd_sql)
        create_result = self.pri_sh.execut_db_sql(cmd_sql)
        self.log.info(create_result)
        self.assertTrue(
            create_result.count(self.constant.TABLE_CREATE_SUCCESS) == 5,
            '执行失败:' + step_txt)

        step_txt = '-----step2:使用copy命令插入数据，expect: 数据插入成功-----'
        self.log.info(step_txt)
        text = '-----step2.1: 获取当前主机的IP地址;expect: 成功-----'
        self.log.info(text)
        cmd = "ifconfig -a|grep inet6 -a2|grep broadcast|awk '{print $2}'"
        self.log.info(cmd)
        self.cur_ip = subprocess.getoutput(cmd).strip()
        self.log.info(self.cur_ip)

        text = '-----step2.2: 复制文件到数据库主机对应目录 expect: 成功-----'
        self.log.info(text)
        if self.cur_ip == self.pri_sh.node.ssh_host:
            self.log.info('当前主机是数据库主机，无需远程复制')
            cmd = f"cp {self.cur_path_1} {self.parent_path};" \
                f"cp {self.cur_path_2} {self.parent_path};" \
                f"cp {self.cur_path_3} {self.parent_path};" \
                f"cp {self.cur_path_4} {self.parent_path};" \
                f"cp {self.cur_path_5} {self.parent_path};"
            self.log.info(cmd)
            res = self.pri_sh.node.sh(cmd).result()
            self.log.info(res)
        else:
            self.com.scp_file(self.pri_root, self.copy_file1,
                              self.parent_path)
            self.com.scp_file(self.pri_root, self.copy_file2,
                              self.parent_path)
            self.com.scp_file(self.pri_root, self.copy_file3,
                              self.parent_path)
            self.com.scp_file(self.pri_root, self.copy_file4,
                              self.parent_path)
            self.com.scp_file(self.pri_root, self.copy_file5,
                              self.parent_path)
            chmod_cmd = f"chmod 777 -R {self.parent_path};" \
                        f"ls -al {self.parent_path}"
            self.log.info(chmod_cmd)
            chmod_result = self.pri_root.sh(chmod_cmd).result()
            self.log.info(chmod_result)

        text = '-----step2.3: 查看数据库主机目标路径下文件 expect: 成功-----'
        self.log.info(text)
        cmd = f"ls -l {self.parent_path}| grep -E '{self.copy_file1}';" \
            f"ls -l {self.parent_path}| grep -E '{self.copy_file2}';" \
            f"ls -l {self.parent_path}| grep -E '{self.copy_file3}';" \
            f"ls -l {self.parent_path}| grep -E '{self.copy_file4}';" \
            f"ls -l {self.parent_path}| grep -E '{self.copy_file5}';"
        self.log.info(cmd)
        res = self.pri_root.sh(cmd).result()
        self.log.info(res)
        self.assertNotIn('No such file or directory', res, '文件拷贝失败')
        self.assertIn(f'{self.copy_file1}', res, '文件拷贝失败')
        self.assertIn(f'{self.copy_file2}', res, '文件拷贝失败')
        self.assertIn(f'{self.copy_file3}', res, '文件拷贝失败')
        self.assertIn(f'{self.copy_file4}', res, '文件拷贝失败')
        self.assertIn(f'{self.copy_file5}', res, '文件拷贝失败')

        text = '-----step2.4:使用copy命令插入数据，expect: 数据插入成功-----'
        self.log.info(text)
        self.log.info('---------------使用copy命令插入数据------------------')
        copy_sql = f"copy {self.table_name1} from '{self.target_path1}' " \
            f"delimiters ',';" \
            f"copy {self.table_name2} from '{self.target_path2}' " \
            f"delimiters ',';" \
            f"copy {self.table_name3} from '{self.target_path3}' " \
            f"delimiters ',';" \
            f"copy {self.table_name4} from '{self.target_path4}' " \
            f"delimiters ',';" \
            f"copy {self.table_name5} from '{self.target_path5}'" \
            f"delimiters ',';"
        self.log.info(copy_sql)
        copy_result = self.pri_sh.execut_db_sql(copy_sql)
        self.log.info(copy_result)
        self.assertIn('COPY 18000', copy_result, '执行失败:' + step_txt)
        self.assertIn('COPY 20', copy_result, '执行失败:' + step_txt)
        self.assertIn('COPY 35', copy_result, '执行失败:' + step_txt)
        self.assertIn('COPY 5', copy_result, '执行失败:' + step_txt)

        step_txt = '-----step3: minus多表联合查询 expect: 成功-----'
        self.log.info(step_txt)
        cmd_sql = f"""
        select trim(sm_ship_mode_sk,'2')::int,count(8)
        from {self.table_name4}
        where length(trim(sm_type))=7
        group by trim(sm_ship_mode_sk,'2')
        minus 
        select instr(r_reason_desc,'o',2,1)-2,r_reason_sk
        from {self.table_name5}
        group by instr(r_reason_desc,'o',2,1)-2,r_reason_sk
        having instr(max(r_reason_desc),'o',2,1)<10
        order by 1,2;
        
        select distinct s_division_id,s_rec_start_date,s_market_id,s_division_id
          from {self.table_name1}
         where (s_market_id,s_market_id) in
               (select distinct trim(i_class_id,'3'),trim(i_class_id,'3')
                  from {self.table_name2}
                 where i_category_id is null
                 group by cube(trim(i_class_id,'3'),trim(i_class_id,'3'))
                minus
                select max(w_warehouse_sk)::Varchar ,max(w_warehouse_sk)::Varchar from {self.table_name3} where s_market_id= w_warehouse_sk)
         group by rollup(s_division_id,s_rec_start_date,s_market_id),s_division_id
         order by 1,2,3,4;
         
        select trim(i_class_id,'3'),i_category_id
        from {self.table_name2}
        where i_category_id is null
        group by trim(i_class_id,'3'),i_category_id
        minus 
        select '',w_warehouse_sk
        from {self.table_name3}
        group by w_city,w_warehouse_sk
        order by 1,2;"""
        self.log.info(cmd_sql)
        query_result = self.pri_sh.execut_db_sql(cmd_sql)
        self.log.info(query_result)
        self.assertIn('0 rows', query_result, '执行失败:' + step_txt)
        self.assertIn('10 rows', query_result, '执行失败:' + step_txt)

    def tearDown(self):
        step_txt = '-----step4: 环境清理 expect:清理成功-----'
        self.log.info(step_txt)
        self.log.info('删除表')
        cmd_sql = self.pri_sh.execut_db_sql(f"""
                    drop table {self.table_name1} cascade;
                    drop table {self.table_name2} cascade;
                    drop table {self.table_name3} cascade;
                    drop table {self.table_name4} cascade;
                    drop table {self.table_name5} cascade;""")
        self.log.info(cmd_sql)
        text = '-----删除文件-----'
        self.log.info(text)
        rm_cmd = f"rm -rf {self.target_path1};" \
            f"rm -rf {self.target_path2};" \
            f"rm -rf {self.target_path3};" \
            f"rm -rf {self.target_path4};" \
            f"rm -rf {self.target_path5};"
        self.log.info(rm_cmd)
        self.com.get_sh_result(self.pri_root, rm_cmd)
        for s in [self.target_path1, self.target_path2]:
            cmd = f'if [ -f {s} ]; then echo "does exists"; ' \
                f'else echo "not exists"; fi'
            file_judgments = self.com.get_sh_result(self.pri_root, cmd)
            self.assertIn('not exists', file_judgments, "清理失败" + text)
        self.assertTrue(
            cmd_sql.count(self.constant.DROP_TABLE_SUCCESS) == 5,
            '执行失败:' + step_txt)
        self.log.info(f'----- {os.path.basename(__file__)} end-----')
